package cn.wd.user.controller;


import cn.hutool.json.JSONUtil;
import cn.wd.common.vo.R;
import cn.wd.model.LoginInfo;
import cn.wd.user.domain.entity.LoginLog;
import cn.wd.user.model.LoginBody;
import cn.wd.user.service.IEmployeeService;
import cn.wd.user.utils.GetTime2Date;
import cn.wd.user.utils.TokenManager;
import cn.wd.user.vo.JsonResult;
import cn.wd.util.CacheKey;
import cn.wd.util.RedisService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoginController {

    private static final Integer maxErrorTimes = 2;

    private final IEmployeeService employeeService;
    private final RedisService redisService;

    public LoginController(RedisService redisService, IEmployeeService employeeService) {
        this.redisService = redisService;
        this.employeeService = employeeService;
    }

    @RequestMapping("/v1/login")
    public JsonResult<String> login(String username, String password, HttpServletRequest req) {

        HttpSession session = req.getSession();

        // 获取之前的错误次数进行 +1
        Integer newErrorTimes = (Integer) session.getAttribute("newErrorTimes");
        if (newErrorTimes == null) {
            // 兼容第一次访问, 如果是第一次, 直接设置为 0
            newErrorTimes = 0;
        }

        // 获取 session 里的 isAccountLockout 账号锁定标志
        Boolean isAccountLockout = (Boolean) session.getAttribute("isAccountLockout");
        if (isAccountLockout == null) {
            isAccountLockout = false;
        }

        // 获取 session 里的 accountLockoutGetTime 账号被冻结时的时间戳
        Long accountLockoutGetTime = (Long) session.getAttribute("accountLockoutGetTime");
        if (accountLockoutGetTime == null) {
            accountLockoutGetTime = 0L;
        }

        // 没被锁定进入登录业务
        if (!isAccountLockout) {
            try {
                // 登录业务
                String loginObject = employeeService.login(username, password);

                // 登录成功后清除错误次数
                session.removeAttribute("newErrorTimes");
                LoginLog log = new LoginLog();
                return JsonResult.success(loginObject);
            } catch (Exception e) {

                // 剩余错误次数提示
                String residueErrorTimesMsg;

                // 如果在最大错误次数内, 就 +1 并提示密码错误还剩余 xx 次机会!
                if (newErrorTimes >= maxErrorTimes - 1) {
                    residueErrorTimesMsg = "密码错误次数过多, 账户已锁定, 请半小时后再尝试!";

                    // 把账号进行锁定
                    isAccountLockout = true;
                    session.setAttribute("isAccountLockout", isAccountLockout);

                    // 账号被锁定的时间戳
                    accountLockoutGetTime = System.currentTimeMillis();
                    session.setAttribute("accountLockoutGetTime", accountLockoutGetTime);
                } else {
                    newErrorTimes++;
                    session.setAttribute("newErrorTimes", newErrorTimes);
                    residueErrorTimesMsg = String.format("剩余%d次机会!", maxErrorTimes - newErrorTimes);
                }

                return JsonResult.failed(400, e.getMessage() + " ,并且" + residueErrorTimesMsg);
            }
        } else {
            // 当前时间戳
            Long nowDateGetTime = System.currentTimeMillis();

            // 两次时间间隔时间戳
            long dateDifference = nowDateGetTime - accountLockoutGetTime;
            System.out.println(dateDifference);
            try {
                // 如果当前时间距离被账号被锁定的时间小于30分钟则抛异常进行提示
                if (dateDifference < 1000 * 30) {
                    String minuteAndSecond = GetTime2Date.getTime2Date(dateDifference);
                    throw new RuntimeException("账号已被锁定,距离解锁还剩[" + minuteAndSecond + "]解锁");
                } else {
                    isAccountLockout = false;
                    session.setAttribute("isAccountLockout", isAccountLockout);

                    // 锁定时间到了当前错误次数进行清空
                    session.removeAttribute("newErrorTimes");
                }
            } catch (Exception ex) {
                return JsonResult.failed(400, ex.getMessage());
            }
            return JsonResult.failed("账户锁定时间已过,请重新登录一次");
        }
    }

    @RequestMapping("/login")
    public R<String> login(@RequestBody @Valid LoginBody loginBody) {
        return R.OK("登录成功", employeeService.login(loginBody));
    }

    @RequestMapping("/logout")
    public JsonResult<?> logout(@RequestHeader(value = TokenManager.TOKEN_NAME, required = false) String token) {
        if (StringUtils.hasText(token)) {
            TokenManager.remove(token);
        }

        LoginInfo loginInfo = redisService.get(CacheKey.getTokenUserKey(token));
        if (loginInfo != null) {
            redisService.delete(CacheKey.getTokenKey(loginInfo.getUsername()));
            redisService.delete(CacheKey.getTokenUserKey(token));
        }
        return JsonResult.success();
    }
}
